package com.lx.util;

import com.lx.annotation.Note;
import com.lx.util.exception.ResultServiceException;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
class OtherUtil {

    //说明: 字符串是否为空白
    /** @author ylx 2022/12/21 15:30 */
    public static boolean isBlank(String s){
        return s == null || s.isEmpty();
    }
    /**为空则返回true，不否则返回false*/
    public static boolean isEmpty(Object s){
        if (s == null){
            return true;
        } else if (s instanceof String str) {
            return str.isEmpty();
        } else if (s instanceof Map map){
            return  map.size()==0;
        }else if(s instanceof Collection list){
            return  list.size()==0;
        }else if(s instanceof Object [] objs){
            return objs.length==0;
        }else if(s instanceof int [] objs){
            return objs.length==0;
        }else if(s instanceof long [] objs){
            return objs.length==0;
        }else if(s instanceof byte [] objs){
            return objs.length==0;
        }else if(s instanceof short [] objs){
            return objs.length==0;
        }else if(s instanceof float [] objs){
            return objs.length==0;
        }else if(s instanceof double [] objs){
            return objs.length==0;
        }else if(s instanceof boolean [] objs){
            return objs.length==0;
        }else if(s instanceof char [] objs){
            return objs.length==0;
        }
        return false;
    }
    /**对象不为null*/
    public static boolean isNotEmpty(Object s){return !isEmpty(s);}
    /**  map中是否包含所有指定的值 */
    public static boolean isNotEmptyMap(Map map,String keys){
        if (isNotEmpty(map) && isNotEmpty(keys)){
            for (String object : keys.split(",")) {
                if(isEmpty(map.get(object.trim()))){
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    /**抛异常*/
    public static <T>T exMsg(boolean boo,String msg){
        if (boo){
            throw new ResultServiceException(msg);
        }
        return null;
    }
    public static <T>T exMsg(boolean boo,String msg, int errCode){
        if (boo){
            throw new ResultServiceException(msg, errCode);
        }
        return null;
    }
    /**判断对象为空时抛异常*/
    public static void exObj(Object s){exObj(s,"值不能为空!");}
    /** 判断对象为空时抛异常*/
    public static void exObj(Object s,String exMsg){
        if(isEmpty(s)){
            LX.exMsg(exMsg);
        }
    }
    public static void exMap(Map s ,String msg, String[] keys){
        try {
            exMap(s,keys);
        }catch (Exception e){
            log.error("调用异常!", e);
            throw new RuntimeException(msg);
        }
    }
    /**判断map中key对应的value值是否为空*/
    public static void exMap(Map s , String[] keys){
        exObj(s);
        exObj(keys);
        StringBuilder sb = new StringBuilder();
        for (String object : keys) {
            if(isEmpty(s.get(object.trim()))){
                sb.append("没有获取到:"+object);
            }
        }
        if (!sb.isEmpty()){
            LX.exMsg(sb.toString());
        }
    }
    /** 上次生成ID的时间截 */
    private static long LAST_TIME_STAMP = -1L;
    /** 上一次的毫秒内序列值 */
    private static long LAST_SEQ = 0L;
    private static Random random = new Random();
    public synchronized static long snowid() {
        long now = System.currentTimeMillis() / 1000; // 使用秒级时间戳
        LX.exMsg(now < LAST_TIME_STAMP, "系统时间错误! 拒绝生成雪花ID");
        if (now == LAST_TIME_STAMP) {
            LAST_SEQ = (LAST_SEQ + 1) & 0xFFFFF; // 限制序列号为20位
            if (LAST_SEQ == 0) {
                while (now <= LAST_TIME_STAMP) {
                    now = System.currentTimeMillis() / 1000;
                    LX.sleep(1000);
                }
            }
        } else {
            LAST_SEQ = random.nextInt(0x7FFFF);
        }
        LAST_TIME_STAMP = now;
        // 组合：32位时间戳 + 20位序列号 = 52位
        return (now << 20) | (LAST_SEQ & 0xFFFFF);
    }
    /**左对齐*/
    public static String left(String str,int i,char c){
        if(str.length()>=i){
            return str.substring(0,i);
        }
        StringBuilder sb = new StringBuilder(str);
        for (int j=0;j<i-str.length();j++){
            sb.append(c);
        }
        return sb.toString();

    };
    /**右对齐*/
    public static String right(String str,int i,char c){
        if(str.length()>=i){
            return str.substring(str.length()-i);
        }
        StringBuilder sb = new StringBuilder();
        for (int j=0;j<i-str.length();j++){
            sb.append(c);
        }
        return sb.append(str).toString();
    };


    /**获取resource指定配置文件*/
    public static Map<String,String> loadProperties(String fileName){
        ResourceBundle prb = ResourceBundle.getBundle(fileName);
        Map<String,String> pp = new HashMap<>();
        for (String key : prb.keySet()){
            pp.put(key , prb.getString(key));
        }
        return pp;
    }
    /**获取网络上的properties文件*/
    public static Map<String,String> getNetProperties(String urlPath){
        Properties pro = new Properties();
        try {
            pro.load(new URL(urlPath).openConnection().getInputStream());
        } catch (Exception e) {
            LX.exMsg(e);
        }
        return LX.toMap(pro);
    }
    /*睡眠*/
    public static void sleep(long time){
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            LX.exMsg(e.getMessage());
        }
    }


    private final static String LOCAL_IP =  "127.0.0.1";
    public static String getIp(){
        String localHostAddress = LOCAL_IP;
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            while(allNetInterfaces.hasMoreElements()){
                NetworkInterface networkInterface = allNetInterfaces.nextElement();
                Enumeration<InetAddress> address = networkInterface.getInetAddresses();
                while(address.hasMoreElements()){
                    InetAddress inetAddress = address.nextElement();
                    if(inetAddress != null
                            && inetAddress instanceof Inet4Address
                            && !LOCAL_IP.equals(inetAddress.getHostAddress())){
                        localHostAddress = inetAddress.getHostAddress();
                    }
                }
            }
        }catch (Exception e){
        }
        return localHostAddress;
    }


    //说明: InputStream -> byte[]
    /**{ ylx } 2021/6/16 21:30 */
    public static byte[] toByteArray(InputStream input){
        try {
            try(ByteArrayOutputStream output = new ByteArrayOutputStream()){
                byte[] buffer = new byte[4096];
                int n = -1;
                while (-1 != (n = input.read(buffer))) {
                    output.write(buffer, 0, n);
                }
                return output.toByteArray();
            }
        } catch (IOException e) {
            return LX.exMsg(e.getMessage());
        }
    }


    //说明:inputStream转String
    /**{ ylx } 2022/4/2 23:47 */
    public static String streamToString(InputStream inputStream , Charset charset){
        if (inputStream == null){
            return null;
        }
        if (charset == null){
            charset = StandardCharsets.UTF_8;
        }
        try(BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, charset))) {
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                if (!sb.isEmpty()){
                    sb.append("\n");
                }
                sb.append(line);
            }
            return sb.toString();
        }catch (Exception e){
            LX.exMsg(e);
        }
        return "";
    }

    public static void inputStreamToOutputStream(InputStream inputStream , OutputStream outputStream ){
        try {
            byte[] buffer = new byte[4096];
            int n = -1;
            while (-1 != (n = inputStream.read(buffer))) {
                outputStream.write(buffer, 0, n);
            }
            outputStream.flush();
        } catch (IOException e) {
            LX.exMsg(e.getMessage());
        }
    }

    public static String webservice(String asmxUrl, Map<String, String> params) {
        String form = LX.createLinkString(params);
        return LX.http(asmxUrl).body(form).header("Content-Type", "application/x-www-form-urlencoded").send();
    }
    public static String webservice(String wsdlUrl,String method, String nameSpace ,Map<String,String> params){
        StringBuilder sb = new StringBuilder();
        sb.append("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><ns2:").append(method).append(" xmlns:ns2=\"").append(nameSpace).append("\">");
        params.forEach((k,v)->{
            sb.append("<").append(k).append(">").append(v).append("</").append(k).append(">");
        });
        sb.append("</ns2:process></soap:Body></soap:Envelope>");
        System.out.println(sb);
        return LX.http(wsdlUrl).body(sb.toString()).header("Content-Type", "Content-Type: text/xml; charset=utf-8").send();
    }


    public static long getLenght(Object obj) {
        if (obj == null){
            return 0;
        }else if (obj instanceof Map){
            return  ((Map)obj).size();
        }else if(obj instanceof Collection){
            return  ((Collection)obj).size();
        }else if(obj instanceof Object []){
            return ((Object[])obj).length;
        }else if(obj instanceof int []){
            return ((int[])obj).length;
        }else if(obj instanceof long []){
            return ((long[])obj).length;
        }
        return 0;
    }


    @Note("替换字符串中的字符")
    public static String replace(CharSequence str, int startInclude, int endExclude, char replacedChar) {
        if (isEmpty(str)) {
            return str(str);
        } else {
            String originalStr = str(str);
            int[] strCodePoints = originalStr.codePoints().toArray();
            int strLength = strCodePoints.length;
            if (startInclude > strLength) {
                return originalStr;
            } else {
                if (endExclude > strLength) {
                    endExclude = strLength;
                }

                if (startInclude > endExclude) {
                    return originalStr;
                } else {
                    StringBuilder stringBuilder = new StringBuilder();

                    for(int i = 0; i < strLength; ++i) {
                        if (i >= startInclude && i < endExclude) {
                            stringBuilder.append(replacedChar);
                        } else {
                            stringBuilder.append(new String(strCodePoints, i, 1));
                        }
                    }

                    return stringBuilder.toString();
                }
            }
        }
    }

    public static String str(CharSequence cs) {
        return null == cs ? null : cs.toString();
    }

    /**
     * 将字节数组转为字符串并确保不超过指定字符长度，且不截断UTF-8字符
     * @param bytes 原始字节数组(UTF-8编码)
     * @param maxChars 最大字符数(如5000)
     * @return 截取后的字符串
     */
    public static String byteArrayToString(byte[] bytes, int maxChars) {
        if (bytes == null){
            return null;
        }
        // 快速检查：如果字节数明显不足，直接转换
        if (bytes.length <= maxChars) {
            return new String(bytes, StandardCharsets.UTF_8);
        }
        // 估算最大需要检查的字节范围(UTF-8中每个字符最多4字节)
        int maxBytesToCheck = Math.min(bytes.length, maxChars * 4);
        String fullString = new String(bytes, 0, maxBytesToCheck, StandardCharsets.UTF_8);
        // 如果实际字符数未超限，直接返回
        if (fullString.length() <= maxChars) {
            return fullString;
        }
        // 精确截取到maxChars个字符，确保不截断多字节字符
        return truncateUtf8String(fullString, maxChars);
    }

    /**
     * 安全截断UTF-8字符串，确保不破坏多字节字符
     */
    private static String truncateUtf8String(String str, int maxChars) {
        if (str.length() <= maxChars) {
            return str;
        }
        // 回溯找到最后一个完整字符边界
        int endIndex = maxChars;
        while (endIndex > 0 && isMidUtf8Char(str.charAt(endIndex))) {
            endIndex--;
        }
        return str.substring(0, endIndex);
    }

    /**
     * 判断是否是UTF-8多字节字符的中间部分
     */
    private static boolean isMidUtf8Char(char c) {
        // UTF-8后续字节的模式为10xxxxxx
        return (c & 0xC0) == 0x80;
    }
}
